﻿namespace com.game.Public.PoolManager
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using UnityEngine;

    [AddComponentMenu("Path-o-logical/PoolManager/SpawnPool")]
    public sealed class SpawnPool : MonoBehaviour, IEnumerable, IEnumerable<Transform>, IList<Transform>, ICollection<Transform>
    {
        public Dictionary<object, bool> _editorListItemStates = new Dictionary<object, bool>();
        public List<PrefabPool> _perPrefabPoolOptions = new List<PrefabPool>();
        private List<PrefabPool> _prefabPools = new List<PrefabPool>();
        internal List<Transform> _spawned = new List<Transform>();
        public bool dontDestroyOnLoad;
        public bool dontReparent;
        public bool logMessages;
        public bool matchPoolLayer;
        public bool matchPoolScale;
        [HideInInspector]
        public float maxParticleDespawnTime = 60f;
        public string poolName = string.Empty;
        public PrefabsDict prefabs = new PrefabsDict();
        public Dictionary<object, bool> prefabsFoldOutStates = new Dictionary<object, bool>();

        public void Add(Transform item)
        {
            string message = "Use SpawnPool.Spawn() to properly add items to the pool.";
            throw new NotImplementedException(message);
        }

        public void Add(Transform instance, string prefabName, bool despawn, bool parent)
        {
            foreach (PrefabPool pool in this._prefabPools)
            {
                if (pool.prefabGO == null)
                {
                    UnityEngine.Debug.LogError("Unexpected Error: PrefabPool.prefabGO is null");
                    return;
                }
                if (pool.prefabGO.name == prefabName)
                {
                    pool.AddUnpooled(instance, despawn);
                    if (this.logMessages)
                    {
                        UnityEngine.Debug.Log(string.Format("SpawnPool {0}: Adding previously unpooled instance {1}", this.poolName, instance.name));
                    }
                    if (parent)
                    {
                        instance.parent = this.group;
                    }
                    if (!despawn)
                    {
                        this._spawned.Add(instance);
                    }
                    return;
                }
            }
            UnityEngine.Debug.LogError(string.Format("SpawnPool {0}: PrefabPool {1} not found.", this.poolName, prefabName));
        }

        private void Awake()
        {
            if (this.dontDestroyOnLoad)
            {
                UnityEngine.Object.DontDestroyOnLoad(base.gameObject);
            }
            this.group = base.transform;
            if (this.poolName == string.Empty)
            {
                this.poolName = this.group.name.Replace("Pool", string.Empty);
                this.poolName = this.poolName.Replace("(Clone)", string.Empty);
            }
            if (this.logMessages)
            {
                UnityEngine.Debug.Log(string.Format("SpawnPool {0}: Initializing..", this.poolName));
            }
            foreach (PrefabPool pool in this._perPrefabPoolOptions)
            {
                if (pool.prefab == null)
                {
                    UnityEngine.Debug.LogWarning(string.Format("Initialization Warning: Pool '{0}' contains a PrefabPool with no prefab reference. Skipping.", this.poolName));
                }
                else
                {
                    pool.inspectorInstanceConstructor();
                    this.CreatePrefabPool(pool);
                }
            }
            com.game.Public.PoolManager.PoolManager.Pools.Add(this);
        }

        public void Clear()
        {
            throw new NotImplementedException();
        }

        public bool Contains(Transform item)
        {
            string message = "Use IsSpawned(Transform instance) instead.";
            throw new NotImplementedException(message);
        }

        public void CopyTo(Transform[] array, int arrayIndex)
        {
            this._spawned.CopyTo(array, arrayIndex);
        }

        public void CreatePrefabPool(PrefabPool prefabPool)
        {
            if (((this.GetPrefab(prefabPool.prefab) != null) ? 1 : 0) == 0)
            {
                prefabPool.spawnPool = this;
                this._prefabPools.Add(prefabPool);
                this.prefabs._Add(prefabPool.prefab.name, prefabPool.prefab);
            }
            if (!prefabPool.preloaded)
            {
                if (this.logMessages)
                {
                    UnityEngine.Debug.Log(string.Format("SpawnPool {0}: Preloading {1} {2}", this.poolName, prefabPool.preloadAmount, prefabPool.prefab.name));
                }
                prefabPool.PreloadInstances();
            }
        }

        public void Despawn(Transform instance)
        {
            bool flag = false;
            foreach (PrefabPool pool in this._prefabPools)
            {
                if (pool._spawned.Contains(instance))
                {
                    flag = pool.DespawnInstance(instance);
                    break;
                }
                if (pool._despawned.Contains(instance))
                {
                    UnityEngine.Debug.LogError(string.Format("SpawnPool {0}: {1} has already been despawned. You cannot despawn something more than once!", this.poolName, instance.name));
                    return;
                }
            }
            if (!flag)
            {
                UnityEngine.Debug.LogError(string.Format("SpawnPool {0}: {1} not found in SpawnPool", this.poolName, instance.name));
            }
            else
            {
                this._spawned.Remove(instance);
            }
        }

        public void Despawn(Transform instance, float seconds)
        {
            base.StartCoroutine(this.DoDespawnAfterSeconds(instance, seconds, false, null));
        }

        public void Despawn(Transform instance, Transform parent)
        {
            instance.parent = parent;
            this.Despawn(instance);
        }

        public void Despawn(Transform instance, float seconds, Transform parent)
        {
            base.StartCoroutine(this.DoDespawnAfterSeconds(instance, seconds, true, parent));
        }

        public void DespawnAll()
        {
            List<Transform> list = new List<Transform>(this._spawned);
            foreach (Transform transform in list)
            {
                this.Despawn(transform);
            }
        }

        [DebuggerHidden]
        private IEnumerator DoDespawnAfterSeconds(Transform instance, float seconds, bool useParent, Transform parent)
        {
            return new <DoDespawnAfterSeconds>c__Iterator19 { instance = instance, seconds = seconds, useParent = useParent, parent = parent, <$>instance = instance, <$>seconds = seconds, <$>useParent = useParent, <$>parent = parent, <>f__this = this };
        }

        [DebuggerHidden]
        public IEnumerator<Transform> GetEnumerator()
        {
            return new <GetEnumerator>c__Iterator1C { <>f__this = this };
        }

        public GameObject GetPrefab(GameObject prefab)
        {
            foreach (PrefabPool pool in this._prefabPools)
            {
                if (pool.prefabGO == null)
                {
                    UnityEngine.Debug.LogError(string.Format("SpawnPool {0}: PrefabPool.prefabGO is null", this.poolName));
                }
                if (pool.prefabGO == prefab)
                {
                    return pool.prefabGO;
                }
            }
            return null;
        }

        public Transform GetPrefab(Transform prefab)
        {
            foreach (PrefabPool pool in this._prefabPools)
            {
                if (pool.prefabGO == null)
                {
                    UnityEngine.Debug.LogError(string.Format("SpawnPool {0}: PrefabPool.prefabGO is null", this.poolName));
                }
                if (pool.prefabGO == prefab.gameObject)
                {
                    return pool.prefab;
                }
            }
            return null;
        }

        public int IndexOf(Transform item)
        {
            throw new NotImplementedException();
        }

        public void Insert(int index, Transform item)
        {
            throw new NotImplementedException();
        }

        public bool IsSpawned(Transform instance)
        {
            return this._spawned.Contains(instance);
        }

        [DebuggerHidden]
        private IEnumerator ListenForEmitDespawn(ParticleEmitter emitter)
        {
            return new <ListenForEmitDespawn>c__Iterator1A { emitter = emitter, <$>emitter = emitter, <>f__this = this };
        }

        [DebuggerHidden]
        private IEnumerator ListenForEmitDespawn(ParticleSystem emitter)
        {
            return new <ListenForEmitDespawn>c__Iterator1B { emitter = emitter, <$>emitter = emitter, <>f__this = this };
        }

        private void OnDestroy()
        {
            if (this.logMessages)
            {
                UnityEngine.Debug.Log(string.Format("SpawnPool {0}: Destroying...", this.poolName));
            }
            com.game.Public.PoolManager.PoolManager.Pools.Remove(this);
            base.StopAllCoroutines();
            this._spawned.Clear();
            foreach (PrefabPool pool in this._prefabPools)
            {
                pool.SelfDestruct();
            }
            this._prefabPools.Clear();
            this.prefabs._Clear();
        }

        public void Remove(Transform item)
        {
            string message = "Use Despawn() to properly manage items that should remain in the pool but be deactivated.";
            throw new NotImplementedException(message);
        }

        public void RemoveAt(int index)
        {
            throw new NotImplementedException();
        }

        public Transform Spawn(string prefabName)
        {
            Transform prefab = this.prefabs[prefabName];
            return this.Spawn(prefab, Vector3.zero, Quaternion.identity);
        }

        public Transform Spawn(Transform prefab)
        {
            return this.Spawn(prefab, Vector3.zero, Quaternion.identity);
        }

        public Transform Spawn(string prefabName, Transform parent)
        {
            Transform prefab = this.prefabs[prefabName];
            Transform transform2 = this.Spawn(prefab, Vector3.zero, Quaternion.identity);
            transform2.parent = parent;
            return transform2;
        }

        public Transform Spawn(Transform prefab, Transform parent)
        {
            Transform transform = this.Spawn(prefab, Vector3.zero, Quaternion.identity);
            transform.parent = parent;
            return transform;
        }

        public Transform Spawn(string prefabName, Vector3 pos, Quaternion rot)
        {
            Transform prefab = this.prefabs[prefabName];
            return this.Spawn(prefab, pos, rot);
        }

        public ParticleEmitter Spawn(ParticleEmitter prefab, Vector3 pos, Quaternion quat)
        {
            Transform transform = this.Spawn(prefab.transform, pos, quat);
            if (transform == null)
            {
                return null;
            }
            ParticleAnimator component = transform.GetComponent<ParticleAnimator>();
            if (component != null)
            {
                component.autodestruct = false;
            }
            ParticleEmitter emitter = transform.GetComponent<ParticleEmitter>();
            emitter.emit = true;
            base.StartCoroutine(this.ListenForEmitDespawn(emitter));
            return emitter;
        }

        public ParticleSystem Spawn(ParticleSystem prefab, Vector3 pos, Quaternion quat)
        {
            Transform transform = this.Spawn(prefab.transform, pos, quat);
            if (transform == null)
            {
                return null;
            }
            ParticleSystem component = transform.GetComponent<ParticleSystem>();
            base.StartCoroutine(this.ListenForEmitDespawn(component));
            return component;
        }

        public Transform Spawn(Transform prefab, Vector3 pos, Quaternion rot)
        {
            Transform transform;
            foreach (PrefabPool pool in this._prefabPools)
            {
                if (pool.prefabGO == prefab.gameObject)
                {
                    transform = pool.SpawnInstance(pos, rot);
                    if (transform == null)
                    {
                        return null;
                    }
                    if (!this.dontReparent && (transform.parent != this.group))
                    {
                        transform.parent = this.group;
                    }
                    this._spawned.Add(transform);
                    return transform;
                }
            }
            PrefabPool prefabPool = new PrefabPool(prefab);
            this.CreatePrefabPool(prefabPool);
            transform = prefabPool.SpawnInstance(pos, rot);
            transform.parent = this.group;
            this._spawned.Add(transform);
            return transform;
        }

        public Transform Spawn(string prefabName, Vector3 pos, Quaternion rot, Transform parent)
        {
            Transform prefab = this.prefabs[prefabName];
            Transform transform2 = this.Spawn(prefab, pos, rot);
            transform2.parent = parent;
            return transform2;
        }

        public Transform Spawn(Transform prefab, Vector3 pos, Quaternion rot, Transform parent)
        {
            Transform transform = this.Spawn(prefab, pos, rot);
            transform.parent = parent;
            return transform;
        }

        public ParticleEmitter Spawn(ParticleEmitter prefab, Vector3 pos, Quaternion quat, string colorPropertyName, Color color)
        {
            Transform transform = this.Spawn(prefab.transform, pos, quat);
            if (transform == null)
            {
                return null;
            }
            ParticleAnimator component = transform.GetComponent<ParticleAnimator>();
            if (component != null)
            {
                component.autodestruct = false;
            }
            ParticleEmitter emitter = transform.GetComponent<ParticleEmitter>();
            emitter.renderer.material.SetColor(colorPropertyName, color);
            emitter.emit = true;
            base.StartCoroutine(this.ListenForEmitDespawn(emitter));
            return emitter;
        }

        bool ICollection<Transform>.Remove(Transform item)
        {
            throw new NotImplementedException();
        }

        [DebuggerHidden]
        IEnumerator IEnumerable.GetEnumerator()
        {
            return new GetEnumerator>c__Iterator18 { <>f__this = this };
        }

        public override string ToString()
        {
            List<string> list = new List<string>();
            foreach (Transform transform in this._spawned)
            {
                list.Add(transform.name);
            }
            return string.Join(", ", list.ToArray());
        }

        public int Count
        {
            get
            {
                return this._spawned.Count;
            }
        }

        public Transform group { get; private set; }

        public bool IsReadOnly
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public Transform this[int index]
        {
            get
            {
                return this._spawned[index];
            }
            set
            {
                throw new NotImplementedException("Read-only.");
            }
        }

        public Dictionary<string, PrefabPool> prefabPools
        {
            get
            {
                Dictionary<string, PrefabPool> dictionary = new Dictionary<string, PrefabPool>();
                foreach (PrefabPool pool in this._prefabPools)
                {
                    dictionary[pool.prefabGO.name] = pool;
                }
                return dictionary;
            }
        }

        [CompilerGenerated]
        private sealed class <DoDespawnAfterSeconds>c__Iterator19 : IEnumerator, IDisposable, IEnumerator<object>
        {
            internal object $current;
            internal int $PC;
            internal Transform <$>instance;
            internal Transform <$>parent;
            internal float <$>seconds;
            internal bool <$>useParent;
            internal SpawnPool <>f__this;
            internal GameObject <go>__0;
            internal Transform instance;
            internal Transform parent;
            internal float seconds;
            internal bool useParent;

            [DebuggerHidden]
            public void Dispose()
            {
                this.$PC = -1;
            }

            public bool MoveNext()
            {
                uint num = (uint) this.$PC;
                this.$PC = -1;
                switch (num)
                {
                    case 0:
                        this.<go>__0 = this.instance.gameObject;
                        break;

                    case 1:
                        if (this.<go>__0.activeInHierarchy)
                        {
                            this.seconds -= Time.deltaTime;
                            break;
                        }
                        goto Label_00C0;

                    default:
                        goto Label_00C0;
                }
                if (this.seconds > 0f)
                {
                    this.$current = null;
                    this.$PC = 1;
                    return true;
                }
                if (this.useParent)
                {
                    this.<>f__this.Despawn(this.instance, this.parent);
                }
                else
                {
                    this.<>f__this.Despawn(this.instance);
                }
                this.$PC = -1;
            Label_00C0:
                return false;
            }

            [DebuggerHidden]
            public void Reset()
            {
                throw new NotSupportedException();
            }

            object IEnumerator<object>.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }

            object IEnumerator.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }
        }

        [CompilerGenerated]
        private sealed class <GetEnumerator>c__Iterator1C : IEnumerator, IDisposable, IEnumerator<Transform>
        {
            internal Transform $current;
            internal int $PC;
            internal List<Transform>.Enumerator <$s_79>__0;
            internal SpawnPool <>f__this;
            internal Transform <instance>__1;

            [DebuggerHidden]
            public void Dispose()
            {
                uint num = (uint) this.$PC;
                this.$PC = -1;
                switch (num)
                {
                    case 1:
                        try
                        {
                        }
                        finally
                        {
                            this.<$s_79>__0.Dispose();
                        }
                        break;
                }
            }

            public bool MoveNext()
            {
                uint num = (uint) this.$PC;
                this.$PC = -1;
                bool flag = false;
                switch (num)
                {
                    case 0:
                        this.<$s_79>__0 = this.<>f__this._spawned.GetEnumerator();
                        num = 0xfffffffd;
                        break;

                    case 1:
                        break;

                    default:
                        goto Label_00A9;
                }
                try
                {
                    while (this.<$s_79>__0.MoveNext())
                    {
                        this.<instance>__1 = this.<$s_79>__0.Current;
                        this.$current = this.<instance>__1;
                        this.$PC = 1;
                        flag = true;
                        return true;
                    }
                }
                finally
                {
                    if (!flag)
                    {
                    }
                    this.<$s_79>__0.Dispose();
                }
                this.$PC = -1;
            Label_00A9:
                return false;
            }

            [DebuggerHidden]
            public void Reset()
            {
                throw new NotSupportedException();
            }

            Transform IEnumerator<Transform>.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }

            object IEnumerator.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }
        }

        [CompilerGenerated]
        private sealed class <ListenForEmitDespawn>c__Iterator1A : IEnumerator, IDisposable, IEnumerator<object>
        {
            internal object $current;
            internal int $PC;
            internal ParticleEmitter <$>emitter;
            internal SpawnPool <>f__this;
            internal float <safetimer>__0;
            internal ParticleEmitter emitter;

            [DebuggerHidden]
            public void Dispose()
            {
                this.$PC = -1;
            }

            public bool MoveNext()
            {
                uint num = (uint) this.$PC;
                this.$PC = -1;
                switch (num)
                {
                    case 0:
                        this.$current = null;
                        this.$PC = 1;
                        goto Label_0104;

                    case 1:
                        this.$current = new WaitForEndOfFrame();
                        this.$PC = 2;
                        goto Label_0104;

                    case 2:
                        this.<safetimer>__0 = 0f;
                        break;

                    case 3:
                        break;

                    default:
                        goto Label_0102;
                }
                if (this.emitter.particleCount > 0)
                {
                    this.<safetimer>__0 += Time.deltaTime;
                    if (this.<safetimer>__0 > this.<>f__this.maxParticleDespawnTime)
                    {
                        UnityEngine.Debug.LogWarning(string.Format("SpawnPool {0}: Timed out while listening for all particles to die. Waited for {1}sec.", this.<>f__this.poolName, this.<>f__this.maxParticleDespawnTime));
                    }
                    this.$current = null;
                    this.$PC = 3;
                    goto Label_0104;
                }
                this.emitter.emit = false;
                this.<>f__this.Despawn(this.emitter.transform);
                this.$PC = -1;
            Label_0102:
                return false;
            Label_0104:
                return true;
            }

            [DebuggerHidden]
            public void Reset()
            {
                throw new NotSupportedException();
            }

            object IEnumerator<object>.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }

            object IEnumerator.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }
        }

        [CompilerGenerated]
        private sealed class <ListenForEmitDespawn>c__Iterator1B : IEnumerator, IDisposable, IEnumerator<object>
        {
            internal object $current;
            internal int $PC;
            internal ParticleSystem <$>emitter;
            internal SpawnPool <>f__this;
            internal float <safetimer>__0;
            internal ParticleSystem emitter;

            [DebuggerHidden]
            public void Dispose()
            {
                this.$PC = -1;
            }

            public bool MoveNext()
            {
                uint num = (uint) this.$PC;
                this.$PC = -1;
                switch (num)
                {
                    case 0:
                        this.$current = new WaitForSeconds(this.emitter.startDelay + 0.25f);
                        this.$PC = 1;
                        goto Label_0118;

                    case 1:
                        this.<safetimer>__0 = 0f;
                        break;

                    case 2:
                        break;

                    default:
                        goto Label_0116;
                }
                if (this.emitter.IsAlive(true))
                {
                    if (!PoolManagerUtils.activeInHierarchy(this.emitter.gameObject))
                    {
                        this.emitter.Clear(true);
                        goto Label_0116;
                    }
                    this.<safetimer>__0 += Time.deltaTime;
                    if (this.<safetimer>__0 > this.<>f__this.maxParticleDespawnTime)
                    {
                        UnityEngine.Debug.LogWarning(string.Format("SpawnPool {0}: Timed out while listening for all particles to die. Waited for {1}sec.", this.<>f__this.poolName, this.<>f__this.maxParticleDespawnTime));
                    }
                    this.$current = null;
                    this.$PC = 2;
                    goto Label_0118;
                }
                this.<>f__this.Despawn(this.emitter.transform);
                this.$PC = -1;
            Label_0116:
                return false;
            Label_0118:
                return true;
            }

            [DebuggerHidden]
            public void Reset()
            {
                throw new NotSupportedException();
            }

            object IEnumerator<object>.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }

            object IEnumerator.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }
        }

        [CompilerGenerated]
        private sealed class GetEnumerator>c__Iterator18 : IEnumerator, IDisposable, IEnumerator<object>
        {
            internal object $current;
            internal int $PC;
            internal List<Transform>.Enumerator <$s_69>__0;
            internal SpawnPool <>f__this;
            internal Transform <instance>__1;

            [DebuggerHidden]
            public void Dispose()
            {
                uint num = (uint) this.$PC;
                this.$PC = -1;
                switch (num)
                {
                    case 1:
                        try
                        {
                        }
                        finally
                        {
                            this.<$s_69>__0.Dispose();
                        }
                        break;
                }
            }

            public bool MoveNext()
            {
                uint num = (uint) this.$PC;
                this.$PC = -1;
                bool flag = false;
                switch (num)
                {
                    case 0:
                        this.<$s_69>__0 = this.<>f__this._spawned.GetEnumerator();
                        num = 0xfffffffd;
                        break;

                    case 1:
                        break;

                    default:
                        goto Label_00A9;
                }
                try
                {
                    while (this.<$s_69>__0.MoveNext())
                    {
                        this.<instance>__1 = this.<$s_69>__0.Current;
                        this.$current = this.<instance>__1;
                        this.$PC = 1;
                        flag = true;
                        return true;
                    }
                }
                finally
                {
                    if (!flag)
                    {
                    }
                    this.<$s_69>__0.Dispose();
                }
                this.$PC = -1;
            Label_00A9:
                return false;
            }

            [DebuggerHidden]
            public void Reset()
            {
                throw new NotSupportedException();
            }

            object IEnumerator<object>.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }

            object IEnumerator.Current
            {
                [DebuggerHidden]
                get
                {
                    return this.$current;
                }
            }
        }
    }
}

